package com.avfh.netcard.util;

import com.avfh.netcard.common.Constant;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.util.StringUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;

public class WxPayKit {
    static Prop prop = PropUtils.use("application.properties");

    public static String packageSign(Map<String, String> params, boolean urlEncoder) {
        TreeMap sortedParams = new TreeMap(params);
        StringBuilder sb = new StringBuilder();
        boolean first = true;
        Iterator iterator = sortedParams.entrySet().iterator();

        while (iterator.hasNext()) {
            Map.Entry param = (Map.Entry) iterator.next();
            String value = (String) param.getValue();
            if (!StringUtils.isEmpty(value)) {
                if (first) {
                    first = false;
                } else {
                    sb.append("&");
                }

                sb.append((String) param.getKey()).append("=");
                if (urlEncoder) {
                    try {
                        value = urlEncode(value);
                    } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                    }
                }

                sb.append(value);
            }
        }

        return sb.toString();
    }

    private static String urlEncode(String src) throws UnsupportedEncodingException {
        return URLEncoder.encode(src, "UTF-8").replace("+", "%20");
    }

    public static String createSign(Map<String, String> params, String key) {
        params.remove("sign");
        String stringA = packageSign(params, false);
        String stringSignTemp = stringA + "&key=" + key;
        return DigestUtils.md5Hex(stringSignTemp).toUpperCase();
    }

    public static boolean verifyNotify(Map<String, String> params, String key) {
        String sign = params.get("sign");
        String localSign = createSign(params, key);
        return sign.equals(localSign);
    }

    public static String toXml(Map<String, String> params) {
        StringBuilder xml = new StringBuilder();
        xml.append("<xml>");
        Iterator i$ = params.entrySet().iterator();

        while (i$.hasNext()) {
            Map.Entry entry = (Map.Entry) i$.next();
            String key = (String) entry.getKey();
            String value = (String) entry.getValue();
            if (!StringUtils.isEmpty(value)) {
                xml.append("<").append(key).append(">");
                xml.append((String) entry.getValue());
                xml.append("</").append(key).append(">");
            }
        }

        xml.append("</xml>");
        return xml.toString();
    }

    public static Map<String, String> xmlToMap(String xmlStr) {
        Document document = XmlKit.parse(xmlStr);
        Element root = document.getDocumentElement();
        Map<String, String> params = new HashMap<>();
        NodeList list = root.getChildNodes();

        for (int i = 0; i < list.getLength(); ++i) {
            Node node = list.item(i);
            params.put(node.getNodeName(), node.getTextContent());
        }

        params.remove("#text");
        return params;
    }

/*    public static Map<String,String> createCode() {
        Map<String, String> params = new HashMap<>();
        params.put("appid", "wx3b7d4554dcb370f3");
        params.put("redirect_uri", "/api/wxPayNotify/wxNotify");
        params.put("response_type", "code");
        params.put("scope", "snsapi_base");
        params.put("#wechat_redirect", "snsapi_base");


        String response = HttpUtils.post("https://open.weixin.qq.com/connect/oauth2/authorize", toXml(params));
        Map<String, String> resultMap = xmlToMap(response);
        return resultMap;
    }*/

    // 统一下单
    public static Map<String, String> createOrder(Map<String, String> params, String key) {
        params.put("nonce_str", UUIDUtils.getUUID());
        String sign = createSign(params, key);
        params.put("sign", sign);
        Map<String, String> resultMap =
                new OkHttpUtils("https://api.mch.weixin.qq.com/pay/unifiedorder")
                        .post(toXml(params))
                        .execute()
                        .asXmlMap();
//        String response = HttpUtils.post("https://api.mch.weixin.qq.com/pay/unifiedorder", toXml(params));
//        Map<String, String> resultMap = xmlToMap(response);

        String returnCode = resultMap.get("return_code");
        if (StringUtils.isEmpty(returnCode) || !"SUCCESS".equals(returnCode) || resultMap.get("prepay_id") == null) {
            return null;
        }

        return resultMap;
    }


    public static Map<String, String> initParamsJsApi(Map<String, String> params) {
        params.put("trade_type", "JSAPI");
        params.put("appid", Constant.APPID);
        params.put("mch_id", Constant.MCH_ID);
        String remoteIPAddress = prop.get("urlPath");
        String notify_url = remoteIPAddress + "/api/wxPayNotify/wxNotify";//回调地址
        params.put("notify_url", notify_url);
        Map<String, String> resultMap = createOrder(params, Constant.MCH_KEY);
        if (resultMap == null) {
            return null;
        }
        params.clear();
        params.put("appId", Constant.APPID);
        params.put("timeStamp", System.currentTimeMillis() / 1000 + "");
        params.put("nonceStr", UUIDUtils.getUUID());
        params.put("package", "prepay_id=" + resultMap.get("prepay_id"));
        params.put("signType", "MD5");
        String sign = createSign(params, Constant.MCH_KEY);
        params.put("paySign", sign);
        return params;
    }


}
